//
// Created by Abstergo on 24-6-22.
//

#ifndef GUARD_HPP
#define GUARD_HPP

#include <base/wrapper.hpp>

namespace tbs
{
/**
 *  生命周期守卫
 * @tparam V 数据
 * @tparam E 结束方法
 * @tparam B 开始方法
 */

    template<typename V, void(* E)(V*), void(* B)(V*)> class Guard
    {
    public:
  /**
   * 构造方法
   * @param val
   */
        explicit Guard(V* val);

        /**
         * 转移构造
         * @param other
         */
        Guard(Guard&& other) NO_EXCEPT;

        /**
         * 转移赋值
         * @param other
         * @return
         */
        Guard& operator=(Guard&& other) NO_EXCEPT;

        Guard& operator=(CONST V& val);

        /**
         * 释放保卫的指针
         * @return
         */
        V* release() NO_EXCEPT;

        Guard(CONST Guard& oth) = delete;

        Guard& operator=(CONST Guard& oth) = delete;

        ~Guard();
        /**
         * 获取数据值
         * @return
         */
        V& get() NO_EXCEPT;

    private:
        V* value;
    };



    template<typename T> static inline void delete_ptr_method(T* ptr);

    template<typename T> static inline void delete_array_ptr_method(T* ptr);

    /**
     * 包装守卫
     */
    template<typename V> using WrappedGuard = Guard<Wrapper<V>, WrappedDestruction, nullptr>;

    /**
     * 包装守卫
     */
    template<typename V> using PtrGuard = Guard<V, delete_ptr_method<V>, nullptr>;

    /**
     * 包装守卫
     */
    template<typename V> using ArrayPtrGuard = Guard<V, delete_array_ptr_method<V>, nullptr>;

    /**
     * 产生针对手动开辟的指针的守卫
     * @tparam V 值类型
     * @tparam W 包装值类
     * @tparam ARGS 包装类构造参数
     * @param args
     * @return
     */
    template<typename V> WrappedGuard<V> inline make_function_guard(V& ptr, std::function<void(V&)> releaseAction);
    /**
     * 产生针对手动开辟的数组指针的守卫
     * @tparam V 值类型
     * @tparam W 包装值类
     * @tparam ARGS 包装类构造参数
     * @param args
     * @return
     */
    template<typename V> ArrayPtrGuard<V> inline make_array_ptr_guard(V* ptr);

    /**
     * 产生针对手动开辟的指针的守卫
     * @tparam V 值类型
     * @tparam W 包装值类
     * @tparam ARGS 包装类构造参数
     * @param args
     * @return
     */
    template<typename V> PtrGuard<V> inline make_ptr_guard(V* ptr);

    /**
     *
     * @tparam V 值类型
     * @tparam W 包装值类
     * @tparam ARGS 包装类构造参数
     * @param args
     * @return
     */
    template<typename V, typename W, typename... ARGS> WrappedGuard<V> make_wrapper_guard(ARGS... args);
}
#include "inls/base/Guard.cuh"
#include "inls/base/QuickGuard.cuh"
#endif //GUARD_HPP
